/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package core;

import datamodel.DriverState;
import java.util.Timer;
import java.util.TimerTask;

/**
 *
 * @author Kvest
 */
public class DriverManager 
{
    public static final int MESSAGE_TO_DISPETCHER = 0;
    public static final int TIMER_TIMEOUT = 10 * 60 * 1000;
    private static final int SHOW_TIMER_STATE_ID = 5;
    private static final int TIMER_PERIOD = 1000;
    public static final int UNKNOWN_VALUE = -1;
    
    private static DriverManager manager = null;;
    private static final Object lock = new Object();

    public static DriverManager getManager()
    {
        synchronized(lock)
        {
            if (manager == null)
            {
                manager = new DriverManager();
            }
        }
        
        return manager;
    }

    private int driverID;
    private DriverState currenntState;
    private DriverState nextState;
    private int districtID;
    private int currentOrderID;
    private String currentOrderText;
    private boolean inBlackList;
    private boolean showRecallItem;
    
    private DriverStateChangedListener driverCurrentStateChangedListener;
    private DriverStateChangedListener driverNextStateChangedListener;
    private TimerAction timerActionListener;
    private Runnable timerTimeoutListener;
    
    private Timer timer;
    private long startTime;
    
    private DriverManager()
    {  
        driverID = UNKNOWN_VALUE;
        currenntState = new DriverState(DriverState.EMPTY_STATE_ID, "");
        nextState = new DriverState(DriverState.EMPTY_STATE_ID, "");
        districtID = UNKNOWN_VALUE;
        currentOrderID = UNKNOWN_VALUE;
        currentOrderText = "";
        inBlackList = false;
        showRecallItem = false;
        
        driverCurrentStateChangedListener = null;
        driverNextStateChangedListener = null; 
        timerActionListener = null;
        timerTimeoutListener = null;
    }

    public int getCurrentOrderID() 
    {
        return currentOrderID;
    }

    public void setCurrentOrderID(int currentOrderID) 
    {
        this.currentOrderID = currentOrderID;
    }

    public String getCurrentOrderText() 
    {
        return currentOrderText;
    }

    public void setCurrentOrderText(String currentOrderText) 
    {
        this.currentOrderText = currentOrderText;
    }

    public int getDistrictID() 
    {
        return districtID;
    }

    public void setDistrictID(int districtID) 
    {
        this.districtID = districtID;
    }

    public int getDriverID() 
    {
        return driverID;
    }

    public void setDriverID(int driverID) 
    {
        this.driverID = driverID;
    }

    public DriverState getCurrenntState() 
    {
        return currenntState;
    }

    public void setCurrenntState(DriverState currenntState) 
    {
        DriverState oldState = this.currenntState;
     
        this.currenntState = currenntState;
        
        //Устанавливаем необходимость генерации собития нового заказа
        OrderManager.getManager().setEmitNewOrderEvent(this.currenntState.getId() == 1 || 
                this.currenntState.getId() == 2);
        
        if (driverCurrentStateChangedListener != null)
        {
            driverCurrentStateChangedListener.driverStateChanged(oldState, this.currenntState);
        }
        
        showRecallItem = false;
        emmitTimerTimeoutEvent();
        
        //Выполняем работу с таймером
        if (this.currenntState.getId() == SHOW_TIMER_STATE_ID)
        {
            //Запускаем таймер
            startTimer();
                    
            //Отображаем таймер
            emmitShowTimer();
        }
        else
        {
            //останавливаем таймер
            stopTimer();
                    
            //Скрываем таймер
            emmitHideTimer();
        }
    }

    public void correctTimerTime(long delta)
    {
        startTime -= delta;
    }
    
    private void startTimer()
    {
        //Останавливаем таймер если он работает
        stopTimer();
        
        //Обновляем состояние
        startTime = System.currentTimeMillis();
        emmitTimerValueChanged((int)(System.currentTimeMillis() - startTime));
        
        //Запускаем таймер
        timer = new Timer();
        timer.schedule(new TimerTask()
        {
            public void run()
            {
                int time = (int)(System.currentTimeMillis() - startTime);
                emmitTimerValueChanged(time);
                
                if (time >= TIMER_TIMEOUT && !showRecallItem)
                {
                    //Взводим флаг что надо отображать пункт меню
                    showRecallItem = true;
                    
                    //Дерагаем слушателя таймера
                    emmitTimerTimeoutEvent();
                    
                    //Завершаем таймер
                    //stopTimer();
                };
            }
        }, TIMER_PERIOD, TIMER_PERIOD);
    }
    
    private void stopTimer()
    {
        if (timer == null)
        {
            return;
        }
        
        try
        {
            timer.cancel();
        }
        catch(Exception ex){}
        
        timer = null;
    }
    
    public DriverState getNextState() 
    {
        return nextState;
    }

    public void setNextState(DriverState nextState) 
    {
        DriverState oldState = this.nextState;
        
        this.nextState = nextState;
        
        if (driverNextStateChangedListener != null)
        {
            driverNextStateChangedListener.driverStateChanged(oldState, this.nextState);
        }
    }

    public void setDriverCurrentStateChangedListener(DriverStateChangedListener driverCurrentStateChangedListener) 
    {
        this.driverCurrentStateChangedListener = driverCurrentStateChangedListener;
    }

    public void setDriverNextStateChangedListener(DriverStateChangedListener driverNextStateChangedListener) 
    {
        this.driverNextStateChangedListener = driverNextStateChangedListener;
    }

    public interface DriverStateChangedListener
    {
        public void driverStateChanged(DriverState oldState, DriverState newState);
    }

    public boolean isInBlackList() 
    {
        return inBlackList;
    }

    public void setInBlackList(boolean inBlackList) 
    {
        this.inBlackList = inBlackList;
    }

    public void setTimerActionListener(TimerAction timerActionListener) 
    {
        this.timerActionListener = timerActionListener;
    }

    public void setTimerTimeoutListener(Runnable timerTimeoutListener) 
    {
        this.timerTimeoutListener = timerTimeoutListener;
    }

    public boolean isShowRecallItem() 
    {
        return showRecallItem;
    }
    
    private void emmitTimerTimeoutEvent()
    {
        if (timerTimeoutListener != null)
        {
            timerTimeoutListener.run();
        }
    }
    
    private void emmitShowTimer()
    {
        if (timerActionListener != null)
        {
            timerActionListener.showTimer();
        }
    }
    
    private void emmitHideTimer()
    {
        if (timerActionListener != null)
        {
            timerActionListener.hideTimer();
        }
    }
    
    private void emmitTimerValueChanged(int milliseconds)
    {
        if (timerActionListener != null)
        {
            timerActionListener.timerValueChanged(milliseconds);
        }
    }
    
    public interface TimerAction
    {
        public void showTimer();
        public void hideTimer();
        public void timerValueChanged(int milliseconds);
    }
}
